/**
  * fluid - *** APP NAME ***
  * Copyright *** COPYRIGHT ***
  * 
  * Licensed under the terms of the *** LICENSE NAME *** license. 
  * 
  *     fluid Project: http://fluidjs.codeplex.com/
  *        fluid Blog: http://fluidjs.vikasburman.com
  *
  *    Repository: *** APP REPOSITORY *** 
  *  Dependencies: 
  * 	- fluid core
  *     - *** ANY OTHER DEPENDENCIES WITH DETAILS ***
  *
  */
(function($f) { $f.extend.app("*** GUID ***", function(self) {
	
	"use strict";
	
	// NOTES: 
	//	1. This app - plugin template defines majority of structures that can be defined in
	//     a fluid app plugin. 
	//
	//  2. IMPORTANT: All these definitions are IN ADDITION TO what can be defined for a normal plugin
	//     as specified in "plugin-template.debug.js". All those required structures should be picked from 
	//	   that file.
	//
	//  3. ALL OF THESE ARE OPTIONAL. You should keep only relevant structures that
	//     you are planning to use, and should remove anything which is not used.
	//
	//  4. Refer to http://fluidjs.codeplex.com/documentation to know about all possibilities 
	//     and other details.
	
	// vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
	// vvvvvvvvvvvvvvvvvv PRIVATE VARS, FUNCTIONS AND CLASSES vvvvvvvvvvvvvvvvv
	// vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv	
	
	// all private variables, functions and classes 
	// can be defined here
	
	// vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
	// vvvvvvvvvvvvvvvvvvvvvvvvvvvvv APP DEFINITION  vvvvvvvvvvvvvvvvvvvvvvvvvv
	// vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
	
	// plugin configuration
	this.config = {
		// default master container element id
		masterContainerElementId: "",
		
		// default application theme
		defaultTheme: "",
		
		// default host layout
		defaultHostLayout: "",
		
		// default master page file
		defaultMasterPage: "",
		
		// default page url of application
		defaultPageUrl: ""
	};
	
	// list of supported locales by the application
	// format of each object inside should be { locale: "locale id", name: "language name", display: "language name in language itself", charset: "resources charset" }
	// supported locals (inbuilt default)
	this.supportedLocales = [
		{ locale: "en-US", name: "English", display: "English (United States)", charset: "" }, 			
	];
	
	// application themes
	// value of each named theme item here should be
	// <themeName>: { layout: "", masterContainerElementId, "", masterPage: "", include: [ ... ] }
	// "empty" is an inbuilt theme and cannot be defined here
	this.themes = { 
	};
	
	// plugin/feature files which are to be loaded during app initialization process
	// value of each item here should be 
	// { name: "", file: "", cond: "a optional function that returns true/false for conditional include"  }
	// plugins are loaded in specified order one after another
	// only (JS) files can be defined in here
	this.plugins = [ 
	];
	
	// application routes
	// can be used to map real navigation urls with a different structure
	// e.g., fluid://pages/home.home.*.js OR fluid://pages/home.home.page can actually be written as fluid://home
	// any level structure can be created here under, each level can be separated with / in url
	// ideally parameters should not be used, however if given both here and in real navigating
	// url, args passed in navigating url will gets precedence
	this.routes = { 
	};
	
	// global weavings - to be applied to each plugin that has isApplyGlobalWeavings set as true
	// this works in specified order
	// define one item for each weaving - at runtime weavings will be done based on this
	// each item here should be defined such:
	//	{plugin: "" , aspect: "published aspectName", functions: ["func1", "func2"]}
	// NOTE: function names can have * wildcard in one of the following ways: funcName* OR *funcName OR func*Name
	this.globalWeavings = [
	];
	
	// data objects
	// these data objects will automatically be replaced with the instance of given data object definition name
	// these data objects are like state objects and their value is persisted across page refresh
	// value of each named item here should be the qualified definition name of the required data object.
	// data object definition must be defined by inclusion of relevant JS files in "include"
	// each item here can be defined as:
	// <instanceName>: {type: "data object registered type name", isTrackChanges: "true|false", args: {...to pass to type's constructor...}}
	//				   "args" is an optional part, a clone object of args will be used instead of same object
	this.data = {
		// data object instances 
		// are to be defined here
		
		// custom data objects can be defined inside "custom"
		// these data objects should be loaded, saved by layout object itself
		// when referring to these objects for data binding in widgets, these can be defined as "custom.<dataObjectName>"
		custom: {
		}		
	};
	
	// data object validations
	// each validation item can be defined as:
	// {type: "validationType", 
	//	reverse: true|false, 
	//	field: "[custom].dataObjectInstanceName.fieldName", 
	//	message: "errorMessage | {resourceKeyPath}", 
	//	params: "{ params for type of validation}" 
	//	AND: [ <same {type: ...} elements} ]
	//	OR: [ <same {type: ...} elements} ]
	//	}
	// "related" is an optional element - should be used only in cases when certain checkes are to
	// be run only when parent check is true. It can be nested to any depth
	this.validations = [ 
	];
	
	// widgets
	// these widgts (layout) are first loaded in specified container (DOM element id) 
	// and then are binded with given dataObject (data)
	// loading of widgets (layout) is an optional part and if html already exists in specified container, 
	// this can be omitted.
	// the structure of each named element here should be: 
	// { container: "ID of the DOM element", data: "data object name as inside 'data'", layout: "html file name" }
	this.widgets = { 
	};
	
	// load custom data objects of app
	// returns (void):		
	this.loadCustomDataObjects = function() {
	};
	
	// save custom data objects of app
	// returns (void):		
	this.saveCustomDataObjects = function() {
	};
	
	// on before data load handler
	// this is called before data objects are loaded
	// returns (void):		
	this.onBeforeDataLoad = function() {
	};
	
	// on after data load handler
	// this is called after data objects are loaded but data binding is not done yet
	// returns (void):		
	this.onAfterDataLoad = function() {
	};
	
	// before an ajax call to server is made via framework 
	// params:
	// 	plugin (object): plugin object that is hosting/making an ajax call
	//	serviceName (string): name of the service for conditional processings, if any
	//	params (object literal): original params object using which call is being made
	// returns (object literal): original or modified params object - call will be made using this object
	this.onAnyServerRequest = function(plugin, serviceName, params) {
		// return as is by default
		return params;
	};
	
	// on receiving a success from a server response
	// params:
	// 	plugin (object): plugin object that is hosted/made an ajax call
	//	serviceName (string): name of the service for conditional processings, if any
	//	params (object literal): original (or modified) params object for which this response success is received
	//	successResponse (object literal): object having ajax success call parameters
	// returns (object): possibly modified server response object
	this.onAnyServerResponseSuccess = function(plugin, serviceName, params, successResponse) { 
		// return as is by default
		return successResponse;
	};
	
	// on receiving an error from a server response
	// params:
	// 	plugin (object): plugin object that is hosted/made an ajax call
	//	serviceName (string): name of the service for conditional processings, if any
	//	params (object literal): original (or modified) params object for which this response error is received
	//	errorResponse (object literal): object having ajax error call parameters
	// returns (object): possibly modified server response object
	this.onAnyServerResponseError = function(plugin, serviceName, params, errorResponse) { 
		// return as is by default
		return errorResponse;		
	};
	
	// called when browser's online state is changed
	// params:
	//	state (string): browser's current state
	//				    state can be "online" or "offline"
	// returns (void):
	this.onBrowserStateChange = function(state) { 
	};

	// on before plugin load
	// this is called before a plugin has just inatantiated but its pre-init is not called
	// params:
	//	plugin (object): plugin object that is being loaded
	// returns (boolean): 
	//	true: if it is ok to let plugin load
	//	false: if plugin load needs to stop
	this.onBeforePluginLoad = function(plugin) { 
		// return 
		return true;
	};
	
	// on after plugin load
	// this is called after a plugin has completed loading and is also ready
	// params:
	//	plugin (object): plugin object that was loaded
	// returns (void):
	this.onAfterPluginLoad = function(plugin) { 
	};

	// on before feature load
	// this is called before a feature definition is being registered
	// params:
	//	featureDefinition (object): feature definition object that is being registered
	// returns (boolean): 
	//	true: if it is ok to let feature definition to register
	//	false: if feature definition registeration needs to stop
	this.onBeforeFeatureLoad = function(featureDefinition) { 
		// return 
		return true;
	};
	
	// on after feature load
	// this is called after a feature definition was registered and feature attach to target
	// plugins was performed (except feature's include processing completion)
	// params:
	//	featureDefinition (object): feature definition object that was just registered
	// returns (void):
	this.onAfterFeatureLoad = function(featureDefinition) { 
	};
	
	// on before page load
	// this is called before a page has started loading but yet nothing is done
	// at the same time page load cannot be stopped now
	// returns (void):
	this.onBeforePageLoad = function() { 
	};
	
	// on after page load
	// this is called after a page has completed loading and is ready to use
	// returns (void):
	this.onAfterPageLoad = function() { 
	};
	
	// on before page unload
	// this is called before a page  has started unloading but yet nothing is done
	// at the same time page unload cannot be stopped now
	// alerts might not work from this function in certain browsers
	// returns (void):
	this.onBeforePageUnload = function() { 
	};
	
	// on after navigation is completed, panes are loaded
	// and everything is ready and focus is set on main screen
	// this is last place in navigation cycle
	// returns (void):
	this.onReadyAll = function() { 
	};
	
	// called only when default page and navigation functionality is not used
	// this gives a place to load ui as required
	// params:
	//	callback (function): Optional. It is passed when either a new navigation is
	//						 being performed or page is being reloaded
	//						 This is not passed when navigation is hapenning because of
	//                       hashTag change
	//						 IMPORTANT: It is very important that callback is executed
	//						 when navigation is complete - or else framework load cycle will break
	// returns (void):	
	this.onNavigationASync = function(callback) {
		// default implementation
		if (isFunction(callback)) {
			callback(); // to complete navigation cycle
		};
	};
	
	// on login request 
	// this is called when a login is being processed - it should validate login user name and password
	// params:
	//	loginName (string): user login name
	//	password (string): user password
	// returns (string): 
	// 	null: if login credentials are invalid
	// 	an empty string: if credentials are valid and this user has all access
	// 	a string having all denied permissions (rest all are assumed available). The structure of the string should be like:
	// 		"pageid-operation_name", "pageid-operation_name", etc. 
	// 		to signify if access to all operations on the page is denied (but page is still accessible) use "pageid-*"
	// 		to signigy if access to the page itself is denied, use "(pageid)"		
	this.onLoginRequest = function(loginName, password) {
		var denyPermissions = ""; // empty string means, credentials are valid and all pages and operations are available, nothing is denied
		
		// return
		return denyPermissions;
	};
	
	// on license check request 
	// this is called on every new session - it should look for stored (in config) license key and validate it
	// returns (string): 
	// 	null: if license if invalid
	// 	an empty string: if license is valid and no restrictions on features
	// 	a string having all denied features (rest all are assumed available). The structure of the string should be like:
	// 		feature_name, feature_name, etc.
	this.onLicenseCheckRequest = function() {
		var denyFeatures = ""; // empty string means, license key is valid and all features are available, nothing is denied
		
		// return
		return denyFeatures;
	};
	
	// on get license key
	// this is called when license key is required for display or some processing
	// returns (string): returns current license key of application as stored in config
	this.onGetLicenseKey = function() {
		return "";
	};
	
	// on login 
	// this is called when user successfully logged in
	// returns (void):
	this.onLogin = function() { 
	};
	
	// on logout
	// this is called when user logs out
	// returns (void):
	this.onLogout = function() { 
	};
	
	// on application error
	// this is called if framework catches any unhandled error
	// params: 
	//	message (string): error message
	//	url (string): url of the document in which error is
	//	lineNumber (number): line number of the document where error is
	// returns (boolean):		
	//	true: if no error dialog is required
	//	false: if an error dialog is required
	this.onApplicationError = function(message, url, lineNumber) {
		// return
		return false;
	};
}); }(fluid));